﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;

namespace OverStore.Runtime
{
    /// <summary>
    /// The exception that is thrown when error occured during persisting instance or collection.
    /// Exception message composes from the messages of all inner exceptions hierarchy separated with new line.
    /// </summary>
    public class PersistingRuntimeException : Exception
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="PersistingRuntimeException"/> class.
        /// </summary>
        public PersistingRuntimeException()
            : base()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PersistingRuntimeException"/> class.
        /// </summary>
        /// <param name="message">The message.</param>
        public PersistingRuntimeException(string message)
            : base(message)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PersistingRuntimeException"/> class.
        /// </summary>
        /// <param name="message">The error message that explains the reason for the exception.</param>
        /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
        public PersistingRuntimeException(string message, Exception innerException)
            : base(CollectExceptionMessages(message, innerException), innerException)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="PersistingRuntimeException"/> class.
        /// This constructor initialize exception exactly with specified message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <param name="innerException">The inner exception.</param>
        /// <param name="dummyUseExactMessage">Value of this parameter is ignored.</param>
        public PersistingRuntimeException(string message, Exception innerException, bool dummyUseExactMessage)
            : base(message, innerException)
        {
        }

        private static string CollectExceptionMessages(Exception innerException)
        {
            var builder = new StringBuilder();
            var ex = innerException;
            while (ex != null)
            {
                builder.AppendLine(ex.Message);
                ex = ex.InnerException;
            }
            return builder.ToString();
        }

        private static string CollectExceptionMessages(string message, Exception innerException)
        {
            return message + Environment.NewLine + CollectExceptionMessages(innerException);
        }
    }
}
